home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / ixemul_src.lha / ixemul-41.0 / library / machdep.c < prev    next >
C/C++ Source or Header  |  1995-05-27  |  19KB  |  660 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  machdep.c,v 1.1.1.1 1994/04/04 04:30:40 amiga Exp
  20.  *
  21.  *  machdep.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:40  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.5  1993/11/05  21:59:18  mwild
  26.  *  add code to deal with inet.library
  27.  *
  28.  *  Revision 1.4  1992/10/20  16:25:24  mwild
  29.  *  no nasty 'c' polling in DEF-signalhandler...
  30.  *
  31.  *  Revision 1.3  1992/08/09  20:57:59  amiga
  32.  *  add volatile to sysbase access, or the optimizer takes illegal shortcuts...
  33.  *
  34.  *  Revision 1.2  1992/07/04  19:20:20  mwild
  35.  *  add yet another state in which not to force a context switch.
  36.  *  Probably unnecessary paranoia...
  37.  *
  38.  * Revision 1.1  1992/05/14  19:55:40  mwild
  39.  * Initial revision
  40.  *
  41.  */
  42.  
  43. #define KERNEL
  44. #include "ixemul.h"
  45. #include "kprintf.h"
  46.  
  47. #include <exec/execbase.h>
  48.  
  49. extern struct ExecBase *SysBase;
  50.  
  51. /* jump to pc in supervisor mode, usp is set to USP before */
  52. extern void volatile supervisor (u_int pc, u_int usp);
  53.  
  54. /* context restore functions for 68000 and 68020 rsp */
  55.  
  56. /* takes the sigcontext * from the usp and restores it 
  57.  * Assumes it's called by Supervisor(), ie. with an exception frame
  58.  */
  59. extern void volatile do_sigreturn (void);
  60.  
  61. /*
  62.  * These two are callable with jsr from supervisor mode, and then
  63.  * set up a fake exception frame and call do_sigreturn().
  64.  */
  65. extern void volatile sup00_do_sigreturn_ssp (u_int ssp);
  66. extern void volatile sup00_do_sigreturn (void);
  67. extern void volatile restore_00 ();
  68. extern void volatile sup20_do_sigreturn_ssp (u_int ssp);
  69. extern void volatile sup20_do_sigreturn (void);
  70. extern void volatile restore_20 ();
  71. /*
  72.  * Either one of sup{00,20}_do_sigreturn, set by configure_context_switch ();
  73.  */
  74. static void volatile (*sup_do_sigreturn) (void);
  75. static void volatile (*sup_do_sigreturn_ssp) (u_int ssp);
  76.  
  77. void setrun (struct Task *t);
  78. void sendsig(struct user *p, sig_t catcher, int sig, int mask, unsigned code, void *addr);
  79. void sig_exit ();
  80.  
  81. /*
  82.  * NOTE: this variable belongs to ixemulbase, not to the current task. But
  83.  *       due to the nature of launch/switch, we can access them here without
  84.  *       locking. It quite a natural thing to do actually ;-)
  85.  */
  86. struct user *curproc;
  87.  
  88. struct sigframe {
  89.   int            sf_signum;    /* signo for handler */
  90.   int            sf_code;    /* additional info for handler */
  91.   void            *sf_addr;    /* yet another info for handler ;-)) */
  92.   sig_t            sf_handler;    /* handler addr for u_sigc */
  93.   struct sigcontext     sf_sc;        /* actual context */
  94. };
  95.  
  96.  
  97. void
  98. configure_context_switch ()
  99. {
  100. if(betterthan68000())
  101.     {
  102.       sup_do_sigreturn = sup20_do_sigreturn;
  103.       sup_do_sigreturn_ssp = sup20_do_sigreturn_ssp;
  104.     }
  105. else
  106.     {
  107.       sup_do_sigreturn = sup00_do_sigreturn;
  108.       sup_do_sigreturn_ssp = sup00_do_sigreturn_ssp;
  109.     }
  110. }
  111.  
  112. void volatile
  113. sigreturn (struct sigcontext *sc)
  114. {
  115.   supervisor ((u_int) do_sigreturn, (u_int) sc);
  116. }
  117.  
  118. void volatile
  119. sig_trampoline (struct sigframe sf)
  120. {
  121.   if (u.u_a4)
  122.     asm ("movel %0,a4" : : "g" (u.u_a4));
  123.   sf.sf_handler (sf.sf_signum, sf.sf_code, sf.sf_addr, & sf.sf_sc);
  124.  
  125.   sigreturn (& sf.sf_sc);
  126. }
  127.  
  128. /*
  129.  * This one is executed in Supervisor mode, just before dispatching this
  130.  * task, so be as quick as possible here !
  131.  */
  132. void
  133. sig_launch () 
  134. {
  135.   struct ExecBase    *SysBase     = *(struct ExecBase **) 4;
  136.   struct Task         *me         = SysBase->ThisTask;
  137.   /* precalculate struct user, so we don't have to go thru SysBase all the time */
  138.   struct user         *p         = (struct user *) me->tc_TrapData;
  139.   sigset_t         sigmsg         = sigmask (SIGMSG);
  140.   sigset_t        sigint         = sigmask (SIGINT);
  141.   sigset_t         newsigs;
  142.   int             i;
  143.   u_int            usp, orig_usp;
  144.   struct sigcontext     *sc;
  145.   u_int            ret_pc, ret_ssp;
  146.  
  147.   usp = orig_usp = get_usp () + 8;     /* set up by our glue_launch() stub */
  148.   
  149.   /* remember who we are */
  150.   curproc = p;
  151.   /* if we're inside ix_sleep, no signal processing is done to break the
  152.      Wait there as soon as possible. Signals resume on return of ix_sleep */
  153.   if (p->p_stat == SSLEEP)
  154.     return;
  155.  
  156.   /* special processing for Wait()ing in Commodore inet.library. They
  157.      do reasonable interrupt checking, but only on SIGBREAKF_CTRL_C. So
  158.      whenever we have a signal to deliver, send ^C.. */
  159.   if (p->p_stat == SWAIT)
  160.     {
  161. #if 0
  162. /* not working clean yet, have to think of a more elaborate solution later */
  163.  
  164.       /* handle ^C here, since we're going to unconditionally raise it 
  165.      afterwards. */
  166.       if (!(p->p_sigignore & sigmask(SIGINT)) && SetSignal (0, SIGBREAKF_CTRL_C))
  167.         p->p_sig |= sigmask (SIGINT);
  168. #endif
  169.  
  170.       if (CURSIG (p))
  171.         Signal (me, SIGBREAKF_CTRL_C);
  172.       return;
  173.     }
  174.  
  175.  
  176.   /* smells kludgy I know...... */
  177.   if (me->tc_TDNestCnt >= 0 || me->tc_IDNestCnt >= 0)
  178.     return;
  179.  
  180.   /* the glue passes us the values of the pc and ssp to restore, if we should
  181.    * decide to sup_do_sigreturn_ssp() out of here, instead of leaving harmlessly..
  182.    */
  183.   ret_pc  = ((u_int *)usp)[-2];
  184.   ret_ssp = ((u_int *)usp)[-1];
  185.   
  186.   /* push a sigcontext that will get us back if no other signals
  187.    * were produced */
  188.   usp -= sizeof (struct sigcontext);
  189.   sc = (struct sigcontext *) usp;
  190.   set_usp (usp);
  191.   
  192.   sc->sc_onstack = p->u_onstack;
  193.   sc->sc_mask     = p->p_sigmask;
  194.   sc->sc_sp     = orig_usp;
  195.   /* the OS context restore function expects a5 to contain the usp, so
  196.    * we have to obey.. */
  197.   sc->sc_fp     = orig_usp;
  198.   sc->sc_ap     = *(u_int *)&me->tc_Flags;
  199.   sc->sc_pc     = ret_pc;
  200.   sc->sc_ps     = get_sr ();
  201.   
  202.   /*
  203.    * first check amigados signals. If SIGMSG is set to SIG_IGN or SIG_DFL, 
  204.    * we do our default mapping of SIGBREAKF_CTRL_C into SIGINT.
  205.    */
  206.   newsigs      = me->tc_SigRecvd &~ p->u_lastrcvsig;
  207.   p->u_lastrcvsig = me->tc_SigRecvd;
  208.  
  209.   if (p->u_InetBase)
  210.     {
  211.       int urgmask = 1<<p->u_sigurg;
  212.       int iomask  = 1<<p->u_sigio;
  213.       
  214.       if (newsigs & urgmask)
  215.         {
  216.           if (! (p->p_sigignore & sigmask (SIGURG)))
  217.             _psignal (me, SIGURG);
  218.             
  219.           me->tc_SigRecvd &= ~urgmask;
  220.           p->u_lastrcvsig &= ~urgmask;
  221.         }
  222.         
  223.       if (newsigs & iomask)
  224.         {
  225.           if (! (p->p_sigignore & sigmask (SIGIO)))
  226.             _psignal (me, SIGIO);
  227.             
  228.           me->tc_SigRecvd &= ~iomask;
  229.           p->u_lastrcvsig &= ~iomask;
  230.         }
  231.     }
  232.  
  233.  
  234.   if (((p->p_sigignore & sigmsg) || !(p->p_sigcatch & sigmsg)) 
  235.       && (newsigs & SIGBREAKF_CTRL_C))
  236.     {
  237.       /* in that case send us a SIGINT, if it's not ignored */
  238.       if (!(p->p_sigignore & sigint))
  239.         _psignal (me, SIGINT);
  240.         
  241.       /* in this mode we fully handle and use SIGBREAKF_CTRL_C, so remove it
  242.        * from the Exec signal mask */
  243.        
  244.       me->tc_SigRecvd &= ~SIGBREAKF_CTRL_C;
  245.       p->u_lastrcvsig &= ~SIGBREAKF_CTRL_C;
  246.     }
  247.   else if (newsigs && (p->p_sigcatch & sigmsg))
  248.     {
  249.       /* if possible, deliver the signal directly to get a code argument */
  250.       if (!(p->p_flag & STRC) && !(p->p_sigmask & sigmsg))
  251.         {
  252.           p->u_ru.ru_nsignals++;
  253.           sendsig(p, p->u_signal[SIGMSG], SIGMSG, p->p_sigmask, newsigs, 0);
  254.           p->p_sigmask |= p->u_sigmask[SIGMSG] | sigmsg;
  255.           setrun (me);
  256.         }
  257.       else
  258.         _psignal (me, SIGMSG);
  259.     }
  260.  
  261.   /* stack watch.. NEVER do this when vforked, the sp is out of bounds then.. */
  262.   if (ix.ix_watch_stack && p->u_red_zone && ! p->p_vfork_msg && ! p->u_onstack)
  263.     {
  264.       if (((void *) usp) < p->u_red_zone)
  265.         _psignal (me, SIGSEGV);
  266.     }
  267.  
  268.   if (i = CURSIG(p))
  269.       psig (p, i);
  270.  
  271.   /* now try to optimize. We could always call sup_do_sigreturn here, but if no
  272.    * signals generated frames, we can just as well simply return, after having
  273.    * restored our usp */
  274.   if (usp == get_usp ())
  275.     {
  276.       /* this is probably not even necessary, since after processing sig_launch
  277.        * the OS reinstalls the usp as me->tc_SPReg, but I guess it's cleaner to
  278.        * do it explicitly here, to show that we reset usp to what it was before
  279.        */
  280.       set_usp (orig_usp);
  281.       return;
  282.     }
  283.  
  284.   sup_do_sigreturn_ssp (ret_ssp);
  285. }
  286.  
  287.  
  288. /*
  289.  * nothing magic about this... when leaving, we note that no process is currently
  290.  * executing (at least none under our control ;-))
  291.  */
  292.  
  293. void
  294. switch_glue ()
  295. {
  296.   curproc = 0;
  297. }
  298.  
  299.  
  300. /*
  301.  * Send an interrupt to process.
  302.  * Called from psig() which is called from sig_launch, thus we are in
  303.  * SUPERVISOR .
  304.  */
  305. void
  306. sendsig (struct user *p, sig_t catcher, int sig, int mask, unsigned code, void *addr)
  307. {
  308.   struct ExecBase    *SysBase     = *(struct ExecBase **) 4;
  309.   struct Task        *me        = SysBase->ThisTask;
  310.   u_int         usp, orig_usp;
  311.   struct sigframe     *sf;
  312.   struct sigcontext    *sc;
  313.   int            oonstack;
  314.  
  315.   orig_usp = get_usp();    /* get value to restore later */
  316.  
  317.   oonstack = p->u_onstack;
  318.  
  319.   if (!p->u_onstack && (p->u_sigonstack & sigmask(sig)))
  320.     {
  321.       p->u_onstack = 1;
  322.       usp = (u_int) p->u_sigsp;
  323.     }
  324.   else
  325.     usp = orig_usp;
  326.   
  327.   /* push signal frame */
  328.   usp -= sizeof (struct sigframe);
  329.   sf = (struct sigframe *) usp;
  330.   
  331.   /* fill out the frame */
  332.   sf->sf_signum        = sig;
  333.   sf->sf_code          = code;
  334.   sf->sf_addr           = addr;
  335.   sf->sf_handler       = catcher;
  336.   sf->sf_sc.sc_onstack = oonstack;
  337.   sf->sf_sc.sc_mask    = mask;
  338.   sf->sf_sc.sc_sp      = (int) orig_usp;    /* previous sigcontext */
  339.   sf->sf_sc.sc_fp      = 0;
  340.   sf->sf_sc.sc_ap      = *(u_int *)&me->tc_Flags;
  341.   sf->sf_sc.sc_ps      = get_sr ();        /* we're in supervisor then */
  342.   sf->sf_sc.sc_pc      = (int) sup_do_sigreturn;/* this pc will restore it */
  343.  
  344.   /* push a signal context to call sig_trampoline */
  345.   usp -= sizeof (struct sigcontext);
  346.   sc = (struct sigcontext *) usp;
  347.  
  348.   /*
  349.    * NOTE: we set the default of a handler to Permit(), Enable(). I guess this
  350.    *       makes sense, since if either Forbid() or Disable() is active, it
  351.    *       shouldn't be possible to invoke a signal anyway, EXCEPT if the
  352.    *       task is Wait()ing, then the OS calls Switch() directly while
  353.    *       either Disable() or Forbid() is active (depends on OS version).
  354.    */
  355.  
  356.   sc->sc_onstack = p->u_onstack;
  357.   sc->sc_mask    = p->p_sigmask;
  358.   sc->sc_sp     = ((int) sf) - 4; /* so that sp@(4) is the argument */
  359.   sc->sc_fp     = 0;
  360.   sc->sc_ap     = (me->tc_Flags << 24) | (me->tc_State << 16) |
  361.              ((u_char)(-1) << 8) | (u_char)(-1);
  362.   sc->sc_ps     = 0;    /* thus we switch into user-mode now! */
  363.   sc->sc_pc     = (int) sig_trampoline;
  364.   
  365.   set_usp (usp);
  366. }
  367.  
  368.  
  369. /*
  370.  * called as the default action of a signal that terminates the process
  371.  */
  372. void
  373. sig_exit (unsigned int code)
  374. {
  375. #ifndef QUIET_SIGEXIT
  376.   /* the whole purpose of this code inside `ifndef QUIET_SIGEXIT' is to
  377.    * prettyprint and identify the job that just terminates
  378.    * This stuff should be handled by a shell, but since there's (yet) no
  379.    * shell that knows how to interpret a signal-exit code (ored with 0x80)
  380.    * I have to do it here myself...
  381.    */
  382.  
  383.   extern char *sys_siglist[NSIG];
  384.   struct Process *me = (struct Process *)((*(struct ExecBase **)4)->ThisTask);
  385.   char err_buf[255];
  386.   struct CommandLineInterface *cli;
  387.   char process_name[255];
  388.   int is_fg;
  389.  
  390.   /* output differs depending on
  391.    *  o  whether we're a CLI or a WB process (stderr or requester)
  392.    *  o  whether this is a foreground or background process
  393.    *  o  whether this is SIGINT or not
  394.    */
  395.  
  396.   /* make sure we're not interrupted in this last step.. */
  397.   syscall (SYS_sigsetmask, ~0);
  398.   
  399.   if (cli = BTOCPTR (me->pr_CLI))
  400.     {
  401.       char *tmp = BTOCPTR (cli->cli_CommandName);
  402.       int   len = *tmp++;
  403.       
  404.       if (len > sizeof (process_name) - 1)
  405.         len = sizeof (process_name) - 1;
  406.       
  407.       bcopy (tmp, process_name, len);
  408.       process_name[len] = 0;
  409.       
  410.       is_fg = cli->cli_Interactive && !cli->cli_Background;
  411.  
  412.     }
  413.   else
  414.     {
  415.       process_name[0] = 0;
  416.       if (me->pr_Task.tc_Node.ln_Name)
  417.         strncpy (process_name, me->pr_Task.tc_Node.ln_Name, sizeof (process_name) - 1);
  418.         
  419.       /* no WB process is ever considered fg */
  420.       is_fg = 0;
  421.  
  422.     }
  423.  
  424.   /* if is_fg and SIGINT, simulate tty-driver and display ^C */
  425.   if (!(is_fg && (code == SIGINT)))
  426.     {
  427.       strcpy (err_buf, (code < NSIG) ? sys_siglist[code] : "Unknown signal");
  428.  
  429.  
  430.       /* if is_fg, don't display the job */
  431.       if (! is_fg)
  432.         {
  433.           strcat (err_buf, " - ");
  434.       strcat (err_buf, process_name);
  435.           /* if we're a CLI we have an argument line saved, that we can print
  436.            * as well */
  437.       if (cli)
  438.               {
  439.           int line_len;
  440.           char *cp;
  441.           
  442.           /* we can display upto column 77, this should be save on all normal
  443.            * amiga CLI windows */
  444.           line_len = 77 - strlen (err_buf) - 1;
  445.           if (line_len > u.u_arglinelen)
  446.             line_len = u.u_arglinelen;
  447.  
  448.           if (line_len > 0 && u.u_argline)
  449.             {
  450.               strcat (err_buf, " ");
  451.           strncat (err_buf, u.u_argline, line_len);
  452.         }
  453.  
  454.           /* now get rid of possible terminating line feeds/cr's */
  455.           for (cp = err_buf; *cp && *cp != '\n' && *cp != '\r'; cp++) ;
  456.           *cp = 0;
  457.         }
  458.     }
  459.  
  460.       if (cli)
  461.         {
  462.           /* uniformly append ONE line feed */
  463.       strcat (err_buf, "\n");
  464.           syscall (SYS_write, 2, err_buf, strlen (err_buf));
  465.         }
  466.       else
  467.         ix_panic (err_buf);
  468.     }
  469.   else
  470.     syscall (SYS_write, 2, "^C\n", 3);
  471. #endif  
  472.  
  473.   syscall (SYS_exit, code | 0x80);
  474.   /* not reached */
  475. }
  476.  
  477. /*
  478.  * This is used to awaken a possibly sleeping sigsuspend()
  479.  * and to force a context switch, if we send a signal to ourselves
  480.  */
  481. void
  482. setrun (struct Task *t)
  483. {
  484.   struct user *p = (struct user *) t->tc_TrapData;
  485.   volatile struct ExecBase *SysBase = *(volatile struct ExecBase **)4;
  486.   u_int curr_disp;
  487.   u_int    sr;
  488.  
  489.   /* NOTE: the context switch is done to make sure sig_launch() is called as
  490.    *       soon as possible in the respective task. It's not nice if you can
  491.    *       return from a kill() to yourself, before the signal handler had a
  492.    *       chance to react accordingly to the signal..
  493.    */
  494.   asm volatile (" 
  495.     movel a5,a0
  496.     lea      pc@(Lget_sr),a5
  497.     movel 4:w,a6
  498.     jsr      a6@(-0x1e)
  499.     movel a1,%0
  500.     bra      Lskip
  501. Lget_sr:
  502.     movew sp@,a1    | get sr register from the calling function
  503.     rte
  504. Lskip:
  505.     movel a0,a5
  506.     " : "=g" (sr) : : "a0", "a1", "a6");
  507.  
  508.   /* Don't force context switch if:
  509.      o  running in Supervisor mode
  510.      o  we setrun() some other process
  511.      o  running under either Forbid() or Disable() */
  512.   if ((sr & 0x2000) || SysBase->ThisTask != t || p->p_stat == SSLEEP ||
  513.       p->p_stat == SWAIT || SysBase->TDNestCnt >= 0 || SysBase->IDNestCnt >= 0)
  514.     {
  515.       extern int select();
  516.  
  517.       /* make testing of p_stat and reaction atomic */
  518.       Disable ();
  519.  
  520.       if (p->p_stat == SWAIT)
  521.         Signal (t, SIGBREAKF_CTRL_C);
  522.       else if (p->p_wchan == (caddr_t) p)
  523.     {
  524.       KPRINTF (("setrun $%lx\n", p));
  525.           ix_wakeup (p);
  526.         }
  527.       else if (p->p_wchan == (caddr_t) select)
  528.         Signal (t, 1<<p->u_sleep_sig);
  529.         
  530.       Enable ();
  531.       return;
  532.     }
  533.   for (curr_disp = SysBase->DispCount; curr_disp == SysBase->DispCount; ) ;
  534.   /* this quite brute-force method, but the only thing I could think of that
  535.    * really guarantees that there was a context switch.. */
  536. }
  537.  
  538. /*
  539.  * Mapping from vector numbers into signals
  540.  */
  541. const static int hwtraptable[256] = {
  542.   SIGILL, /* Reset initial stack pointer */
  543.   SIGILL, /* Reset initial program counter */
  544.   SIGBUS, /* Bus Error */
  545.   SIGBUS, /* Address Error */
  546.   SIGILL, /* Illegal Instruction */
  547.   SIGFPE, /* Zero Divide */
  548.   SIGFPE, /* CHK, CHK2 Instruction */
  549.   SIGFPE, /* cpTRAPcc, TRAPcc, TRAPV Instruction */
  550.   SIGILL, /* Privilege Violation */
  551.   SIGTRAP,/* Trace */
  552.   SIGEMT, /* Line 1010 Emulator */
  553.   SIGEMT, /* Line 1111 Emulator */
  554.   SIGILL,
  555.   SIGILL, /* Coprocessor Protocol Violation */
  556.   SIGILL, /* Format Error */
  557.   SIGILL, /* Uninitialized Interrupt */
  558.   SIGILL, /* 16 */
  559.   SIGILL, /* 17 */
  560.   SIGILL, /* 18 */
  561.   SIGILL, /* 19 */        /* unimplemented, reserved */
  562.   SIGILL, /* 20 */
  563.   SIGILL, /* 21 */
  564.   SIGILL, /* 22 */
  565.   SIGILL, /* 23 */
  566.   SIGILL, /* spurious Interrupt */
  567.   SIGILL, /* Level 1 Interrupt Autovector */
  568.   SIGILL, /* Level 2 Interrupt Autovector */
  569.   SIGILL, /* Level 3 Interrupt Autovector */
  570.   SIGILL, /* Level 4 Interrupt Autovector */
  571.   SIGILL, /* Level 5 Interrupt Autovector */
  572.   SIGILL, /* Level 6 Interrupt Autovector */
  573.   SIGILL, /* Level 7 Interrupt Autovector */
  574.   SIGILL, /* Trap #0 (not available on Unix) */
  575.   SIGILL, /* Trap #1 */
  576.   SIGILL, /* Trap #2 */
  577.   SIGILL, /* Trap #3 */
  578.   SIGILL, /* Trap #4 */
  579.   SIGILL, /* Trap #5 */
  580.   SIGILL, /* Trap #6 */
  581.   SIGILL, /* Trap #7 */
  582.   SIGILL, /* Trap #8 */
  583.   SIGILL, /* Trap #9 */
  584.   SIGILL, /* Trap #10 */
  585.   SIGILL, /* Trap #11 */
  586.   SIGILL, /* Trap #12 */
  587.   SIGILL, /* Trap #13 */
  588.   SIGILL, /* Trap #14 */
  589.   SIGILL, /* Trap #15 (not available on Unix) */
  590.   SIGFPE, /* FPCP Branch or Set on Unordererd Condition */
  591.   SIGFPE, /* FPCP Inexact Result */
  592.   SIGFPE, /* FPCP Divide by Zero */
  593.   SIGFPE, /* FPCP Underflow */
  594.   SIGFPE, /* FPCP Operand Error */
  595.   SIGFPE, /* FPCP Overflow */
  596.   SIGFPE, /* FPCP Signaling NAN */
  597.   SIGILL,
  598.   SIGBUS, /* MMU Configuration Error */
  599.   SIGILL, /* MMU Illegal Operation (only 68851) */
  600.   SIGILL, /* MMU Privilege Violation (only 68851) */
  601.   /* rest undefined or free user-settable.. */
  602. };
  603.  
  604. /*
  605.  * handle traps handled over from the lowlevel trap handlers
  606.  */
  607. void
  608. trap (u_int format, void *addr)
  609. {
  610.   struct ExecBase    *SysBase     = *(struct ExecBase **) 4;
  611.   struct Task         *me         = SysBase->ThisTask;
  612.   /* precalculate struct user, so we don't have to go thru SysBase all the time */
  613.   struct user         *p         = (struct user *) me->tc_TrapData;
  614.   int             sig;
  615.   u_int            usp, orig_usp;
  616.   struct sigcontext     *sc;
  617. #if __GNUC__ != 2 || defined(BROKEN_GCC20)
  618.   int volatile         been_here;
  619. #endif
  620.   u_int            ret_pc, ret_ssp;
  621.  
  622.  
  623.   usp = orig_usp = get_usp () + 8;    /* skip argument parameters */
  624.   ret_pc  = ((u_int *)usp)[-2];
  625.   ret_ssp = ((u_int *)usp)[-1];
  626.   
  627.   /* push a sigcontext that will get us back here if no other signals
  628.    * were produced */
  629.   usp -= sizeof (struct sigcontext);
  630.   sc = (struct sigcontext *) usp;
  631.   set_usp (usp);
  632.  
  633.   sc->sc_onstack = p->u_onstack;
  634.   sc->sc_mask     = p->p_sigmask;
  635.   sc->sc_sp     = orig_usp;
  636.   sc->sc_fp     = get_fp ();
  637.   sc->sc_ap     = *(u_int *)&me->tc_Flags;
  638.   sc->sc_pc     = ret_pc;
  639.   sc->sc_ps     = get_sr ();
  640.  
  641.   /* format contains the vector * 4, in the lower 12 bits */
  642.   sig = *(int *)((u_char *)hwtraptable + (format & 0x0fff));
  643.  
  644.   trapsignal (me, sig, format, addr);
  645.  
  646.   if (sig = CURSIG(p))
  647.     psig (p, sig);
  648.  
  649.   /* now try to optimize. We could always call sup_do_sigreturn here, but if no
  650.    * signals generated frames, we can just as well simply return, after having
  651.    * restored our usp */
  652.   if (usp == get_usp ())
  653.     {
  654.       set_usp (orig_usp);
  655.       return;
  656.     }
  657.  
  658.   sup_do_sigreturn_ssp (ret_ssp);
  659. }
  660.